﻿using System;
using biz.ritter.javapi.lang;
using biz.ritter.javapi.lang.reflect;
using biz.ritter.javapi.util;
using Nofs.Net.Common.Interfaces.Library;
using Nofs.Net.nofs.metadata.interfaces;

namespace Nofs.Net.Fuse.Impl
{
    public class DomainObjectCollectionHelper
    {
        private IDomainObjectContainerManager _containerManager;
        private IAttributeAccessor _accessor;

        public DomainObjectCollectionHelper(IDomainObjectContainerManager containerManager, IAttributeAccessor accessor)
        {
            _containerManager = containerManager;
            _accessor = accessor;
        }

        //@SuppressWarnings("unchecked")
        public void RemoveChildObject(Object parent, Method method, Object child) //throws Exception 
        {
            //incoming assumption is that this operation can succeed
            RemoveChildObject((List)method.invoke(parent, (Object[])null), _accessor.GetInnerCollectionType(method), child);
        }

        //@SuppressWarnings("unchecked")
        public void RemoveChildObject(Object obj, Object child) //throws Exception 
        {
            //incoming assumption is that this operation can succeed
            RemoveChildObject((List)obj, _accessor.GetInnerCollectionType(obj), child);
        }

        //@SuppressWarnings("unchecked")
        private void RemoveChildObject(List objList, Class objType, Object child) //throws Exception 
        {
            IDomainObjectContainer<object> container = _containerManager.GetContainer(objType);
            if (!objList.remove(child))
            {
                throw new System.Exception("Child was not in the list!");
            }
            if (container.IsPersistent(child))
            {
                container.Remove(child);
            }
        }

        //@SuppressWarnings("unchecked")
        public void AddChildObject(Object obj, Method method, String name, MarkerTypes inodeType) //throws Exception 
        {
            //incoming assumption is that this operation can succeed
            //AddChildObject((List)method.invoke(obj, (Object[])null), _accessor.GetInnerCollectionType(method), name);
            AddChildObject(
                    (List)method.invoke(obj, (Object[])null),
                    MarkerTypes.FolderObject == inodeType
                        ? _accessor.FindObjectTypeToCreateForMkDir(obj, method)
                        : _accessor.FindObjectTypeToCreateForMknod(obj, method),
                    name);
        }

        //@SuppressWarnings("unchecked")
        public void AddChildObject(Object obj, String name, MarkerTypes inodeType)// throws Exception 
        {
            //incoming assumption is that this operation can succeed
            //AddChildObject((List)obj, _accessor.GetInnerCollectionType(obj), name);
            AddChildObject(
                    (List)obj,
                    MarkerTypes.FolderObject == inodeType
                        ? _accessor.FindObjectTypeToCreateForMkDir(obj)
                        : _accessor.FindObjectTypeToCreateForMknod(obj),
                    name);
        }

        //@SuppressWarnings("unchecked")
        private void AddChildObject(List objList, Class objType, String name)// throws Exception 
        {
            IDomainObjectContainerInternal container = (IDomainObjectContainerInternal)_containerManager.GetContainer(objType);
            Object newObj = container.NewPersistentInstance();
            _accessor.setNameForObject(newObj, name);
            container.CreateAndSaveStatObjects(newObj);
            objList.add(newObj);
        }

        //@SuppressWarnings("unchecked")
        public void MoveChildObject(Object objToMove, Object sourceCollection, Object destCollection, String newName) //throws Exception 
        {
            //incoming assumption is that this operation can succeed
            List source = (List)sourceCollection;
            List dest = (List)destCollection;
            if (!source.remove(objToMove))
            {
                throw new System.Exception("Child was not in the list!");
            }
            dest.add(objToMove);
            String oldName = _accessor.getNameFromObject(objToMove);
            IDomainObjectContainerInternal container = (IDomainObjectContainerInternal)_containerManager.GetContainer(objToMove.getClass());
            container.UpdateStatObjects(objToMove, oldName, newName);
            _accessor.setNameForObject(objToMove, newName);
        }
    }

}
